package com.getechnologiesmx.flutter.activity;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.PluginRegistry;

/**
 * ActivityPlugin
 */
public class ActivityPlugin implements FlutterPlugin, MethodCallHandler, ActivityAware, PluginRegistry.ActivityResultListener {
    private MethodChannel channel;
    private ActivityPluginBinding _activityBinding;
    private Result result;
    private MethodCall methodCall;

    private static final int METHOD_PAYMENT = 53;
    private static final int METHOD_PAYMENT_CALL = 54;

    @Override
    public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
        channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "com.getechnologiesmx.flutter.activity");
        channel.setMethodCallHandler(this);
    }

    @Override
    public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
        this.methodCall = call;
        this.result = result;

        switch (call.method) {
            case "startActivityForResult":
                startActivityForResult(call, result);
                break;
            default:
                result.notImplemented();
                finishWithSuccess();
                break;
        }
    }

    public void startActivityForResult(@NonNull MethodCall call, @NonNull Result result) {
        if (call.arguments != null) {
            Intent intent = Util.toIntent((Map<String, Object>) call.arguments);
            this._activityBinding.getActivity().startActivityForResult(intent, METHOD_PAYMENT);
        }
    }

    @Override
    public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
        channel.setMethodCallHandler(null);
    }

    @Override
    public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
        this._activityBinding = binding;
        binding.addActivityResultListener(this);
        channel.setMethodCallHandler(this);
    }

    @Override
    public void onDetachedFromActivityForConfigChanges() {

    }

    @Override
    public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) {
    }

    @Override
    public void onDetachedFromActivity() {

    }

    @Override
    public boolean onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        switch (requestCode) {
            case METHOD_PAYMENT:
                resultPayment(requestCode, resultCode, data);
                break;
            default:
                return false;
        }
        return true;
    }

    private void resultPayment(int requestCode, int resultCode, Intent data) {
        Map<String, Object> map = new HashMap<>();
        if (data.getExtras() != null) {
            map = bundleToMap(Objects.requireNonNull(data.getExtras()));
        }
        map.put("requestCode", requestCode);
        map.put("resultCode", resultCode);
        this.result.success(map);
    }

    private void finishWithSuccess() {
        methodCall = null;
        result = null;
    }

    public static Map<String, Object> bundleToMap(Bundle extras) {
        Map<String, Object> map = new HashMap<>();
        Set<String> ks = extras.keySet();
        Iterator<String> iterator = ks.iterator();
        while (iterator.hasNext()) {
            String key = iterator.next();
            map.put(key, extras.getString(key));
        }
        return map;
    }
}
